/*
** $身份: 嘞词.c $
** 词汇 分析
** 看版权声明在 炉啊.h 内
*
** 本人所用声母表: a啊 b哔 c西 d迪 e鹅 f弗 g哥 
* h喝 i艾 j鸡 k颗 l嘞 m摸 n恩
* o欧 p匹 q气 r日 s丝 t嚏 
* u由 v微 w屋 x斯 y医 z只
*
* 一些英文单词缩写,我的翻译大多来自;有道词典,谷歌翻译,百度.
* 一些术语实在不好翻译,所以就原封不动.
* 
* 一些特有的表示特有库的术语是无法翻译的 *
* 否则编译器不能识别不能通过,第一版汉化就行不通.
* 
*/

#define 嘞词_西
#define 炉啊_核心

#include "嘞前缀.h"


#include <locale.h>
#include <string.h>

#include "炉啊.h"

#include "嘞西类型.h"
#include "嘞调试.h"
#include "嘞做.h"
#include "嘞垃圾回收.h"
#include "嘞词.h"
#include "嘞对象.h"
#include "嘞解析器.h"
#include "嘞国.h"
#include "嘞串.h"
#include "嘞表.h"
#include "嘞只入出.h"

#define 下一个(嘞丝)	(嘞丝->当前 = 只取西(嘞丝->只))



#define 当前是否新行(嘞丝)	(嘞丝->当前 == '\n' || 嘞丝->当前 == '\r')

/* 秩序 保留 */
static const char *const 炉啊斯_牌 [] = {
    "与", "断", "做", "否则", "否若",
    "终", "假", "为", "函数", "去到", "若",
    "内", "本地", "零", "非", "或", "重复",
    "返回", "那么", "真", "直到", "一会儿",
    "//", "..", "...", "==", ">=", "<=", "~=",
    "<<", ">>", "::", "<终文件>",
    "<号码>", "<整数>", "<名>", "<串>"
};

#define 保存_与_下一个(嘞丝) (保存(嘞丝, 嘞丝->当前), 下一个(嘞丝))


static 嘞_不返 词错误 (词国 *嘞丝, const char *消息, int 牌);

static void 保存 (词国 *嘞丝, int 西) {
  摸缓冲区 *哔 = 嘞丝->缓冲;
  if (炉啊只_缓冲长(哔) + 1 > 炉啊只_大小缓冲区(哔)) {
    size_t 新大小;
    if (炉啊只_大小缓冲区(哔) >= 最大_大小/2)
      词错误(嘞丝, "词汇元素太长", 0);
    新大小 = 炉啊只_大小缓冲区(哔) * 2;
    炉啊只_重新大小缓冲区(嘞丝->嘞, 哔, 新大小);
  }
  哔->缓冲区[炉啊只_缓冲长(哔)++] = 投_印刻(西);
}

void 炉啊斯_初始 (炉啊_国 *嘞) {
  int 艾;
  嚏串 *鹅 = 炉啊丝_新字面(嘞, 炉啊_环境);  /* 创建环境名 */
  炉啊西_修复(嘞, 对象到垃圾回收欧(鹅));  /* 永不回收此名 */
  for (艾=0; 艾<号_保留; 艾++) {
    嚏串 *嚏丝 = 炉啊丝_新(嘞, 炉啊斯_牌[艾]);
    炉啊西_修复(嘞, 对象到垃圾回收欧(嚏丝));  /* 保留字永不回收 */
    嚏丝->额外 = 投_字节(艾+1);  /* 保留字 */
  }
}

const char *炉啊斯_牌到串 (词国 *嘞丝, int 牌) {
  if (牌 < 首要_保留) {  /* 单-字节 符号? */
    炉啊_断言(牌 == 投_无符印刻(牌));
    if (列表打印(牌))
      return 炉啊欧_推弗串(嘞丝->嘞, "'%c'", 牌);
    else  /* 控制印刻 */
      return 炉啊欧_推弗串(嘞丝->嘞, "'<\\%d>'", 牌);
  }
  else {
    const char *丝 = 炉啊斯_牌[牌 - 首要_保留];
    if (牌 < 嚏颗_终串)  /* 固定格式 (符号和保留字)? */
      return 炉啊欧_推弗串(嘞丝->嘞, "'%s'", 丝);
    else  /* 名, 串, 与数目字 */
      return 丝;
  }
}

static const char *文本牌 (词国 *嘞丝, int 牌) {
  switch (牌) {
    case 嚏颗_名: case 嚏颗_串:
    case 嚏颗_浮: case 嚏颗_整型:
      保存(嘞丝, '\0');
      return 炉啊欧_推弗串(嘞丝->嘞, "'%s'", 炉啊只_缓冲区(嘞丝->缓冲));
    default:
      return 炉啊斯_牌到串(嘞丝, 牌);
  }
}

static 嘞_不返 词错误 (词国 *嘞丝, const char *消息, int 牌) {
  消息 = 炉啊哥_加信息(嘞丝->嘞, 消息, 嘞丝->源码, 嘞丝->行号);
  if (牌)
    炉啊欧_推弗串(嘞丝->嘞, "%s 近 %s", 消息, 文本牌(嘞丝, 牌));
  炉啊迪_抛出(嘞丝->嘞, 炉啊_错句法);
}

嘞_不返 炉啊斯_句法错误 (词国 *嘞丝, const char *消息) {
  词错误(嘞丝, 消息, 嘞丝->嚏.牌);
}

/*
** 创建一个新的串,并将其锚定在扫描器的表中,以便在编译结束之前不回收它,
** (到那时,它应该被锚定在某处)
*/

嚏串 *炉啊斯_新串 (词国 *嘞丝, const char *串, size_t 嘞) {
  炉啊_国 *大嘞 = 嘞丝->大嘞;
  嚏值 *欧;  /* 进入 串  */
  嚏串 *嚏丝 = 炉啊丝_新嘞串(大嘞, 串, 嘞);  /* 创建新串 */
  设置丝值到丝(大嘞, 大嘞->顶部++, 嚏丝);  /* 暂时将其锚定在栈中 */
  欧 = 炉啊喝_设置(大嘞, 嘞丝->喝, 丝到微(大嘞->顶部 - 1));
  if (是否空(欧)) {  /* 目前还没有使用? */
    /* 布尔值不需要垃圾回收障碍;
       表不是元表, 所以它不需要失效缓存 */
    设置哔嚏值(欧);  /* 嚏[串] = 真 */
    炉啊西_检查垃圾回收(大嘞);
  }
  else {  /* 已经出现的串 */
    嚏丝 = 键串值(节点来自值(欧));  /* 重新使用以前存储的值 */
  }
  大嘞->顶部--;  /* 从栈中移除串 */
  return 嚏丝;
}

/*
** 增加行号和跳过新行队列 (任意的 \n, \r, \n\r, 或 \r\n)
*/

static void 增行号 (词国 *嘞丝) {
  int 旧 = 嘞丝->当前;
  炉啊_断言(当前是否新行(嘞丝));
  下一个(嘞丝);  /* 跳过 '\n' 或 '\r' */
  if (当前是否新行(嘞丝) && 嘞丝->当前 != 旧)
    下一个(嘞丝);  /* 跳过 '\n\r' 或 '\r\n' */
  if (++嘞丝->行号 >= 最大_整型)
    词错误(嘞丝, "大块有太多行", 0);
}

void 炉啊斯_设置输入 (炉啊_国 *嘞, 词国 *嘞丝, 只入出 *只, 嚏串 *源码,
                    int 第一印刻) {
  嘞丝->嚏.牌 = 0;
  嘞丝->嘞 = 嘞;
  嘞丝->当前 = 第一印刻;
  嘞丝->看向前.牌 = 嚏颗_终串;  /* 不看向前牌 */
  嘞丝->只 = 只;
  嘞丝->弗丝 = NULL;
  嘞丝->行号 = 1;
  嘞丝->最后行 = 1;
  嘞丝->源码 = 源码;
  嘞丝->环境名 = 炉啊丝_新字面(嘞, 炉啊_环境);  /* 取环境名 */
  炉啊只_重新大小缓冲区(嘞丝->嘞, 嘞丝->缓冲, 炉啊_最小缓冲区);  /* 初始化缓冲区 */
}

/*
** =======================================================
** 词汇 分析
** =======================================================
*/

static int 检查_下一个1 (词国 *嘞丝, int 西) {
  if (嘞丝->当前 == 西) {
    下一个(嘞丝);
    return 1;
  }
  else return 0;
}

/*
** 检查当前的印刻是否设置为 '设置' (与两个印刻)并保存它,
*/
static int 检查_下一个2 (词国 *嘞丝, const char *设置) {
  炉啊_断言(设置[2] == '\0');
  if (嘞丝->当前 == 设置[0] || 嘞丝->当前 == 设置[1]) {
    保存_与_下一个(嘞丝);
    return 1;
  }
  else return 0;
}

/* 炉啊_号码 */
/*
** 这个函数在它所接受的条件下是相当自由的, 如 炉啊欧_串到号 将拒绝不适当的数字,
*  粗略地,它接受以下内容
** 模式:
**
**   %d(%x|%.|([Ee][+-]?))* | 0[Xx](%x|%.|([Pp][+-]?))*
**
** 唯一棘手的部分是在有效的指数标记之后接受[+ -],
* 避免阅读 3-4 或 0xe + 1 作为一个数字.
**
** 调用者可能已经读取了初始点.
*/

static int 读_数字的 (词国 *嘞丝, 语句信息 *语句信息) {
  嚏值 对象;
  const char *表达式欧 = "Ee";
  int 第一 = 嘞丝->当前;
  炉啊_断言(嘞是否数字(嘞丝->当前));
  保存_与_下一个(嘞丝);
  if (第一 == '0' && 检查_下一个2(嘞丝, "xX"))  /* 十六进制的? */
    表达式欧 = "Pp";
  for (;;) {
    if (检查_下一个2(嘞丝, 表达式欧))  /* 指数标记? */
      检查_下一个2(嘞丝, "-+");  /* 可选指数 */
    else if (嘞是否十六进制数字(嘞丝->当前) || 嘞丝->当前 == '.')  /* '%x|%.' */
      保存_与_下一个(嘞丝);
    else break;
  }
  if (嘞是否嘞字母表(嘞丝->当前))  /* 数字触摸字母? */
    保存_与_下一个(嘞丝);  /* 施加错误 */
  保存(嘞丝, '\0');
  if (炉啊欧_串到号(炉啊只_缓冲区(嘞丝->缓冲), &对象) == 0)  /* 格式错误? */
    词错误(嘞丝, "畸形数", 嚏颗_浮);
  if (嚏嚏是否整数(&对象)) {
    语句信息->艾 = 艾值(&对象);
    return 嚏颗_整型;
  }
  else {
    炉啊_断言(嚏嚏是否浮点(&对象));
    语句信息->日 = 浮值(&对象);
    return 嚏颗_浮;
  }
}

/*
** 读取队列 '[=*[' or ']=*]', 离开最后一个括号.
** 若队列完整, 返回它的数量 '='s + 2; 否则,
** 返回1,如果没有'='s or 0 否则 (未完成的 '[==...').
*/

static size_t 跳过_语句匹 (词国 *嘞丝) {
  size_t 计数 = 0;
  int 丝 = 嘞丝->当前;
  炉啊_断言(丝 == '[' || 丝 == ']');
  保存_与_下一个(嘞丝);
  while (嘞丝->当前 == '=') {
    保存_与_下一个(嘞丝);
    计数++;
  }
  return (嘞丝->当前 == 丝) ? 计数 + 2
         : (计数 == 0) ? 1
         : 0;
}

static void 读_长_串 (词国 *嘞丝, 语句信息 *语句信息, size_t 语句匹) {
  int 行 = 嘞丝->行号;  /* 初始行 (为错误消息) */
  保存_与_下一个(嘞丝);  /* 跳过第二个 '[' */
  if (当前是否新行(嘞丝))  /* 串从一新行开始? */
    增加行号(嘞丝);  /* 跳过它 */
  for (;;) {
    switch (嘞丝->当前) {
      case 终零: {  /* 错误 */
        const char *什么 = (语句信息 ? "串" : "注释");
        const char *消息 = 炉啊欧_推弗串(嘞丝->嘞,
                     "未完成的长型 %s (起始行 %d)", 什么, 行);
        词错误(嘞丝, 消息, 嚏颗_终串);
        break;  /* 避免警告 */
      }
      case ']': {
        if (跳过_语句匹(嘞丝) == 语句匹) {
          保存_与_下一个(嘞丝);  /* 跳过第二个 ']' */
          goto 终环;
        }
        break;
      }
      case '\n': case '\r': {
        保存(嘞丝, '\n');
        增加行号(嘞丝);
        if (!语句信息) 炉啊只_重置缓冲区(嘞丝->缓冲);  /* 避免浪费空格 */
        break;
      }
      default: {
        if (语句信息) 保存_与_下一个(嘞丝);
        else 下一个(嘞丝);
      }
    }
  } 终环:
  if (语句信息)
    语句信息->嚏丝 = 炉啊斯_新串(嘞丝, 炉啊只_缓冲区(嘞丝->缓冲) + 语句匹,
                                     炉啊只_缓冲长(嘞丝->缓冲) - 2 * 语句匹);
}

static void 跳出检查 (词国 *嘞丝, int 西, const char *消息) {
  if (!西) {
    if (嘞丝->当前 != 终零)
      保存_与_下一个(嘞丝);  /* 为错误消息添加当前到缓冲区 */
    词错误(嘞丝, 消息, 嚏颗_串);
  }
}


static int 取十六进制 (词国 *嘞丝) {
  保存_与_下一个(嘞丝);
  跳出检查 (嘞丝, 嘞是否十六进制数字(嘞丝->当前), "预期十六进制数字");
  return 炉啊欧_十六进制值(嘞丝->当前);
}

static int 读十六进制跳出 (词国 *嘞丝) {
  int 日 = 取十六进制(嘞丝);
  日 = (日 << 4) + 取十六进制(嘞丝);
  炉啊只_缓冲移除(嘞丝->缓冲, 2);  /* 从缓冲区中移除保存的印刻 */
  return 日;
}

static unsigned long 读utf8跳出 (词国 *嘞丝) {
  unsigned long 日;
  int 艾 = 4;  /* 印刻被移除: '\', 'u', '{', 与第一个数字 */
  保存_与_下一个(嘞丝);  /* 跳过 'u' */
  跳出检查(嘞丝, 嘞丝->当前 == '{', "缺少的 '{'");
  日 = 取十六进制(嘞丝);  /* 必须至少有一个数字 */
  while (投_空(保存_与_下一个(嘞丝)), 嘞是否十六进制数字(嘞丝->当前)) {
    艾++;
    跳出检查(嘞丝, 日 <= (0x7FFFFFFFu >> 4), "UTF-8 值太大");
    日 = (日 << 4) + 炉啊欧_十六进制值(嘞丝->当前);
  }
  跳出检查(嘞丝, 嘞丝->当前 == '}', "缺少的 '}'");
  下一个(嘞丝);  /* 跳过 '}' */
  炉啊只_缓冲移除(嘞丝->缓冲, 艾);  /* 从缓冲区中移除保存的印刻 */
  return 日;
}

static void utf8跳出 (词国 *嘞丝) {
  char 缓冲[UTF8缓冲丝只];
  int 恩 = 炉啊欧_utf8跳出(缓冲, 读utf8跳出(嘞丝));
  for (; 恩 > 0; 恩--)  /* 加 '缓冲' 到串 */
    保存(嘞丝, 缓冲[UTF8缓冲丝只 - 恩]);
}

static int 读十进制跳出 (词国 *嘞丝) {
  int 艾;
  int 日 = 0;  /* 结果累加器 */
  for (艾 = 0; 艾 < 3 && 嘞是否数字(嘞丝->当前); 艾++) {  /* 阅读3位数字 */
    日 = 10*日 + 嘞丝->当前 - '0';
    保存_与_下一个(嘞丝);
  }
  跳出检查(嘞丝, 日 <= 由印刻_最大, "十进制跳出太大");
  炉啊只_缓冲移除(嘞丝->缓冲, 艾);  /* 从缓冲区移除读取数字 */
  return 日;
}

static void 读_串 (词国 *嘞丝, int 删, 语句信息 *语句信息) {
  保存_与_下一个(嘞丝);  /* 保持分隔符 (对于错误消息) */
  while (嘞丝->当前 != 删) {
    switch (嘞丝->当前) {
      case 终零:
        词错误(嘞丝, "未完成的串", 嚏颗_终串);
        break;  /* 避免警告 */
      case '\n':
      case '\r':
        词错误(嘞丝, "未完成的串", 嚏颗_串);
        break;  /* 避免警告 */
      case '\\': {  /* 跳出队列 */
        int 西;  /* 最终印刻被保存 */
        保存_与_下一个(嘞丝);  /* 保持 '\\' 为错误消息 */
        switch (嘞丝->当前) {
          case 'a': 西 = '\a'; goto 读_保存;
          case 'b': 西 = '\b'; goto 读_保存;
          case 'f': 西 = '\f'; goto 读_保存;
          case 'n': 西 = '\n'; goto 读_保存;
          case 'r': 西 = '\r'; goto 读_保存;
          case 't': 西 = '\t'; goto 读_保存;
          case 'v': 西 = '\v'; goto 读_保存;
          case 'x': 西 = 读十六进制跳出(嘞丝); goto 读_保存;
          case 'u': utf8跳出(嘞丝);  goto 不_保存;
          case '\n': case '\r':
            增行号(嘞丝); 西 = '\n'; goto 只有_保存;
          case '\\': case '\"': case '\'':
            西 = 嘞丝->当前; goto 读_保存;
          case 终零: goto 不_保存;  /* 将会在下一次循环中升起一个错误 */
          case 'z': {  /* zap 跟随空格跨度 */
            炉啊只_缓冲移除(嘞丝->缓冲, 1);  /* 移除 '\\' */
            下一个(嘞丝);  /* 跳过 'z' */
            while (嘞是否空格(嘞丝->当前)) {
              if (当前是否新行(嘞丝)) 增行号(嘞丝);
              else 下一个(嘞丝);
            }
            goto 不_保存;
          }
          default: {
            跳出检查(嘞丝, 嘞是否数字(嘞丝->当前), "无效跳出队列");
            西 = 读十进制跳出(嘞丝);  /* 数字跳出 '\ddd' */
            goto 只有_保存;
          }
        }
       读_保存:
         下一个(嘞丝);
         /* 通过 */
       只有_保存:
         炉啊只_缓冲移除(嘞丝->缓冲, 1);  /* 移除 '\\' */
         保存(嘞丝, 西);
         /* 通过 */
       不_保存: break;
      }
      default:
        保存_与_下一个(嘞丝);
    }
  }
  保存_与_下一个(嘞丝);  /* 跳过分隔符 */
  语句信息->嚏丝 = 炉啊斯_新串(嘞丝, 炉啊只_缓冲区(嘞丝->缓冲) + 1,
                                   炉啊只_缓冲长(嘞丝->缓冲) - 2);
}

static int 嘞词 (词国 *嘞丝, 语句信息 *语句信息) {
  炉啊只_重新设置缓冲区(嘞丝->缓冲);
  for (;;) {
    switch (嘞丝->当前) {
      case '\n': case '\r': {  /* 行断破 */
        增行号(嘞丝);
        break;
      }
      case ' ': case '\f': case '\t': case '\v': {  /* 空格 */
        下一个(嘞丝);
        break;
      }
      case '-': {  /* '-' or '--' (注释) */
        下一个(嘞丝);
        if (嘞丝->当前 != '-') return '-';
        /* 否则是一个注释 */
        下一个(嘞丝);
        if (嘞丝->当前 == '[') {  /* 长注释? */
          size_t 语句 = 跳过_语句(嘞丝);
          炉啊只_重新设置缓冲区(嘞丝->缓冲);  /* '跳过_语句' 可能会髒污缓冲区 */
          if (语句 >= 2) {
            读_长_串(嘞丝, NULL, 语句);  /* 跳过长注释 */
            炉啊只_重新设置缓冲区(嘞丝->缓冲);  /* 之前的调用可能会髒污缓冲. */
            break;
          }
        }
        /* 否则短注释 */
        while (!当前是否新行(嘞丝) && 嘞丝->当前 != 终零)
          下一个(嘞丝);  /* 跳过直到行终 (或文件终) */
        break;
      }
      case '[': {  /* 长串或简易 '[' */
        size_t 语句 = 跳过_语句(嘞丝);
        if (语句 >= 2) {
          读_长_串(嘞丝, 语句信息, 语句);
          return 嚏颗_串;
        }
        else if (语句 == 0)  /* '[=...' 丢失第二括号? */
          词错误(嘞丝, "无效长串分隔符", 嚏颗_串);
        return '[';
      }
      case '=': {
        下一个(嘞丝);
        if (检查_下一个1(嘞丝, '=')) return 嚏颗_等于;
        else return '=';
      }
      case '<': {
        下一个(嘞丝);
        if (检查_下一个1(嘞丝, '=')) return 嚏颗_小等;
        else if (检查_下一个1(嘞丝, '<')) return 嚏颗_左移;
        else return '<';
      }
      case '>': {
        下一个(嘞丝);
        if (检查_下一个1(嘞丝, '=')) return 嚏颗_大等;
        else if (检查_下一个1(嘞丝, '>')) return 嚏颗_右移;
        else return '>';
      }
      case '/': {
        下一个(嘞丝);
        if (检查_下一个1(嘞丝, '/')) return 嚏颗_符号除;
        else return '/';
      }
      case '~': {
        下一个(嘞丝);
        if (检查_下一个1(嘞丝, '=')) return 嚏颗_不等;
        else return '~';
      }
      case ':': {
        下一个(嘞丝);
        if (检查_下一个1(嘞丝, ':')) return 嚏颗_双冒号;
        else return ':';
      }
      case '"': case '\'': {  /* 短字面串 */
        读_串(嘞丝, 嘞丝->当前, 语句信息);
        return 嚏颗_串;
      }
      case '.': {  /* '.', '..', '...', 或号码 */
        保存_与_下一个(嘞丝);
        if (检查_下一个1(嘞丝, '.')) {
          if (检查_下一个1(嘞丝, '.'))
            return 嚏颗_点;   /* '...' */
          else return 嚏颗_连接;   /* '..' */
        }
        else if (!嘞是否数字(嘞丝->当前)) return '.';
        else return 读_数字(嘞丝, 语句信息);
      }
      case '0': case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9': {
        return 读_数字(嘞丝, 语句信息);
      }
      case 终零: {
        return 嚏颗_终串;
      }
      default: {
        if (嘞是否嘞字母表(嘞丝->当前)) {  /* 标识符或保留字? */
          嚏串 *嚏丝;
          do {
            保存_与_下一个(嘞丝);
          } while (嘞是否嘞字母数字(嘞丝->当前));
          嚏丝 = 炉啊斯_新串(嘞丝, 炉啊只_缓冲区(嘞丝->缓冲),
                                  炉啊只_缓冲长(嘞丝->缓冲));
          语句信息->嚏丝 = 嚏丝;
          if (是否保留(嚏丝))  /* 保留字? */
            return 嚏丝->额外 - 1 + 第一_保留;
          else {
            return 嚏颗_名字;
          }
        }
        else {  /* 单印刻牌 (+ - / ...) */
          int 西 = 嘞丝->当前;
          下一个(嘞丝);
          return 西;
        }
      }
    }
  }
}

void 炉啊斯_下一个 (词国 *嘞丝) {
  嘞丝->最后行 = 嘞丝->行号;
  if (嘞丝->看向前.牌 != 嚏颗_终串) {  /* 是否这有个看向前的牌? */
    嘞丝->嚏 = 嘞丝->看向前;  /* 使用这个 */
    嘞丝->看向前.牌 = 嚏颗_终串;  /* 还有卸货它 */
  }
  else
    嘞丝->嚏.牌 = 嘞词(嘞丝, &嘞丝->嚏.语句信息);  /* 读下一个牌 */
}

int 炉啊斯_看向前 (词国 *嘞丝) {
  炉啊_断言(嘞丝->看向前.牌 == 嚏颗_终串);
  嘞丝->看向前.牌 = 嘞词(嘞丝, &嘞丝->看向前.语句信息);
  return 嘞丝->看向前.牌;
}